package com.yunji.order.business.remote;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.yunji.common.cache.RedisCache;
import com.yunji.common.utils.JsonUtil;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.order.ali.AliPayoutRespDTO;
import com.yunji.order.bo.PayableBO;
import com.yunji.order.domain.RequestDO;
import com.yunji.order.emuns.PayMode;
import com.yunji.order.emuns.RemoteTypes;
import com.yunji.order.emuns.ResultTypes;
import com.yunji.order.service.RequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.RoundingMode;

import static com.yunji.order.contstant.PayCode.*;

/**
 * @Project: yunji-coffee
 * @Package: com.yunji.order.remote
 * @Title: AlibabaPayable
 * @Description: 支付宝处理
 * <p>
 * History:
 * Date						Version			Author			Summary
 * ========================================================================
 * 2024-04-22 14:02:05		V1.0			HuaAo		新建类
 */
@Component
public class AlibabaPayable {
    private static final Logger logs = LoggerFactory.getLogger(AlibabaPayable.class);

    @Value("${alipay.apply.appid:xxx}")
    private String appid;

    @Value("${yunji.profile:xxx}")
    private String profile;

    @Value("${alipay.apply.privateKey:xxx}")
    private String privateKey;

    @Resource
    RedisCache redisCache;

    // 设置描述特定的业务场景 单笔无密转账固定为 DIRECT_TRANSFER
    private static final String PARAM_DIRECT_TRANSFER = "DIRECT_TRANSFER";

    // 设置业务产品码 单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
    private static final String PARAM_TRANS_ACCOUNT = "TRANS_ACCOUNT_NO_PWD";

    @Resource
    private RequestService requestService;

    /**------------------------------------- 支付宝配置 -------------------------------------**/

    /**
     * @return AlipayConfig 支付宝配置
     * @Title getAlipayConfig
     * @Desc 设置支付宝配置
     * @Date 2024-04-22 19:38:21.357
     */
    private AlipayConfig getAlipayConfig() {
        // 安全创建实例
        AlipayConfig alipay = new AlipayConfig();

        // 应用ID
        alipay.setAppId(appid);

        // 应用公钥证书
        String appPublicKey = profile + "/alipay/appCertPublicKey.crt";
        // 支付根证书
        String alipayRootKey = profile + "/alipay/alipayRootCert.crt";
        // 支付公钥证书
        String alipayPublicKey = profile + "/alipay/alipayCertPublicKey_RSA2.crt";
        alipay.setAppCertPath(appPublicKey);
        alipay.setRootCertPath(alipayRootKey);
        alipay.setAlipayPublicCertPath(alipayPublicKey);

        // 转账固定参数
        alipay.setPrivateKey(privateKey);
        alipay.setServerUrl(ALIPAY_GATEWAY);
        alipay.setCharset(ENCODING_UTF8);
        alipay.setSignType(ALIPAY_SIGN_RSA);
        alipay.setFormat(ALIPAY_DATA_JSON);

        return alipay;
    }

    /**------------------------------------- 转账交易 -------------------------------------**/

    /**
     * @return AlipayFundTransUniTransferModel
     * @Title getPayoutModel
     * @Desc 设置转账参数信息
     * @Date 2024-04-22 19:38:55.982
     */
    private AlipayFundTransUniTransferModel getPayoutModel(PayableBO param) {
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();

        model.setBizScene(PARAM_DIRECT_TRANSFER);
        model.setProductCode(PARAM_TRANS_ACCOUNT);

        // 设置转账业务的标题
        model.setOrderTitle(param.getTradeContent());

        // 设置转账业务请求的扩展参数
        model.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}"); // 是否展示付款方别名 true:展示别名 false:不展示别名。默认为 false
        // 设置业务备注
        model.setRemark(param.getTradeContent());
        // 设置商家侧唯一订单号
        model.setOutBizNo(param.getTradeCode());
        // 设置订单总金额
        model.setTransAmount(String.valueOf(param.getPayout().setScale(2, RoundingMode.HALF_UP)));

        // 设置收款方信息
        Participant payeeInfo = new Participant();
        payeeInfo.setName(param.getRealName());
        payeeInfo.setIdentity(param.getOpenId());
        // ALIPAY_USER_ID:支付宝会员的用户ID
        // ALIPAY_LOGON_ID:支付宝登录号,支持邮箱和手机号格式。
        payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
        logs.info("【支付宝转账】转账人信息{}", payeeInfo);
        model.setPayeeInfo(payeeInfo);

        return model;
    }

    /**
     * @param param 交易参数
     * @Title payoutTrade
     * @Desc 支付宝交易处理
     * @Date 2024-05-10 15:02:36.786
     * @Return Map<String, String> 响应参数
     */
    public AliPayoutRespDTO payoutTrade(PayableBO param) {
        RequestDO request = new RequestDO();
        request.setChannel(PayMode.ALIPAY.getCode());
        request.setRequestType(RemoteTypes.ALIPAY_TRADE_PAYOUT.getCode());
        request.setRequestUrl(ALIPAY_GATEWAY);
        request.setTradeCode(param.getTradeCode());
        try {
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
            // 构造请求参数以调用接口
            AlipayFundTransUniTransferRequest alipayRequest = new AlipayFundTransUniTransferRequest();
            AlipayFundTransUniTransferModel model = getPayoutModel(param);
            String params = BeanUtils.toString(model);
            logs.info("【支付宝转账】请求参数:{}", params);
            request.setRequestParam(params);
            alipayRequest.setBizModel(model);
            AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(alipayRequest);
            String result = response.getBody();
            request.setResponseContent(result);
            request.setResponseCode(response.getCode());
            logs.info("【支付宝转账】响应结果：{}", result);
            boolean success = response.isSuccess();
            if (success)
                request.setStatus(ResultTypes.SUCCESS.getCode());
            else
                request.setStatus(ResultTypes.FAILURE.getCode());
            return new AliPayoutRespDTO(success, response.getOutBizNo(), response.getPayFundOrderId(), response.getOrderId(), response.getTransDate(), response.getSubMsg());
        } catch (Exception e) {
            logs.error("【支付宝转账】支付宝转账失败:{}", JsonUtil.toJsonString(param), e);
            return new AliPayoutRespDTO(false, e.getMessage());
        } finally {
            requestService.createRequest(request);
        }
    }

    /**------------------------------------- 查询转账 -------------------------------------**/

    /**
     * @param tradeCode 交易流水号
     * @Title getResponse
     * @Desc 执行交易查询
     * @Date 2024-05-10 17:57:31.430
     * @Return AlipayFundTransCommonQueryResponse
     */
    private AlipayFundTransCommonQueryResponse getSearchModel(String tradeCode) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
        AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
        AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();

        model.setBizScene(PARAM_DIRECT_TRANSFER);
        model.setProductCode(PARAM_TRANS_ACCOUNT);

        // 设置商户转账唯一订单号
        model.setOutBizNo(tradeCode);

        request.setBizModel(model);

        return alipayClient.certificateExecute(request);
    }

    /**
     * @param tradeCode 交易流水号
     * @Title searchPayout
     * @Desc 查询支付信息
     * @Date 2024-05-10 18:12:52.901
     */
    public AlipayFundTransCommonQueryResponse searchPayout(String tradeCode) throws AlipayApiException {
        AlipayFundTransCommonQueryResponse response = getSearchModel(tradeCode);
        String result = response.getBody();
        logs.info("【支付宝转账查询】查询结果{}", result);
        return response;
    }
}